/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package misc;

import com.jme3.math.Vector3f;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.vecmath.Vector2d;
import javax.vecmath.Vector3d;
import jme3tools.navigation.InvalidPositionException;
import jme3tools.navigation.MapModel2D;
import jme3tools.navigation.MapModel3D;
import jme3tools.navigation.Position;

/**
 *
 * @author hp
 */
public class MapGenerator {

    private int width;
    private int height;
    private int minDistance;
    private int numPersons;
    private File newMap;
    private File newMapSim;
    private FileWriter mapWriter;
    private ArrayList<Vector3f> positions;
    private ArrayList<Rectangle> obstacles;
    private String OUTPUT_DIR = "assets/Scenes/maps_";
    private String mapName;
    private FileWriter simWriter;

    public MapGenerator(int width, int height) {
        this.width = width;
        this.height = height;

    }

    public void generateMap(int numPersons, int minDistance, String dir, File map) {
        positions = new ArrayList<Vector3f>();
        obstacles = new ArrayList<Rectangle>();
        this.numPersons = numPersons;
        mapName = map.getName().substring(0, map.getName().indexOf("."));
        new File(dir).mkdir();
        new File(dir+"_Sim").mkdir();
        newMap = new File(dir + "/" + map.getName());
        newMapSim = new File(dir + "_Sim/" + map.getName());
        try {
            mapWriter = new FileWriter(newMap);
            simWriter = new FileWriter(newMapSim);
            simWriter.write("800 1200\n640 480\n4\n0 0 640 640\n0 480 480 0\n" + numPersons + "\n");
            extractInformation(map);
            this.minDistance = minDistance;
            long seed = System.nanoTime();
            Random rand = new Random(seed);
            
            for (int i = 0; i < numPersons; i++) {
                int newX = rand.nextInt(width);
                int newY = rand.nextInt(height);
                Vector3f newVect = new Vector3f(newX, 0, newY);
                if (!positions.isEmpty()) {
                    while (!isValidPos(newVect)) {
                        newX = rand.nextInt(width);
                        newY = rand.nextInt(height);
                        newVect = new Vector3f(newX, 0, newY);
                    }
                }
                positions.add(newVect);
                Vector3f personInWorld = convertToWorld(newVect);
                mapWriter.write((int) newVect.x + " " + (int) newVect.z + "\n");
                simWriter.write((int) personInWorld.x + " " + 160 + " " + (int) personInWorld.z + "\n");

            }
            mapWriter.write(seed+"\n");
            mapWriter.close();
            simWriter.write(obstacles.size() + "\n");
            for (Rectangle obst : obstacles) {
                int newW = 320 - obst.width / 2;
                int newH = 240 - obst.height / 2;
                Vector3f obsInWorld = convertToWorld(new Vector3f(newW, newH, newH));
                newW = (int) obsInWorld.x;
//                newW = (int) ((int) (newW * 1.0) * (1200.0 / 800.0));
                newH = (int) obsInWorld.z;
//                newH = (int) ((int) (newH * 1.0) * (800.0 / 800.0));
                obsInWorld = convertToWorld(new Vector3f(obst.x, 0, obst.y));
                int newX = (int) (newW - obsInWorld.x);
                newX = -newX;
//                newX = (int) ((int) (newX * 1.0) * (800.0 / 800.0));
                int newY = (int) (obsInWorld.z - newH);
//                newY = (int) ((int) (newY * 1.0) * (1200.0 / 800.0));
                simWriter.write(newW + " " + 150 + " " + newH + " Textures/chessboard.jpg " + newX + " 150 " + newY + "\n");
            }
            simWriter.write("0 1 0 1\n4\n");
            simWriter.write("0.7 1 0.5 1 -400 160 600 225 Top_Right false\n0.4 0.7 0.5 1 400 160 600 315 Top_Left false\n0.4 0.7 0 0.5 400 160 -600 45 Bottom_Left false\n0.7 1 0 0.5 -400 160 -600 135 Bottom_Right false\n");
            simWriter.write(seed+"\n");
            simWriter.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private boolean isValidPos(Vector3f current) {
        for (Vector3f vect : positions) {
            if (vect.distance(current) > minDistance && !isInsideObstacle(current)) {
                return true;
            }
        }
        return false;
    }

    private boolean isInsideObstacle(Vector3f current) {
        Point curr = new Point((int) current.x, (int) current.z);
        for (Rectangle rect : obstacles) {
            if(rect.contains(curr))
                return true;
        }
        return false;
    }

    private void extractInformation(File map) throws IOException {
        File fFile = new File("assets/Scenes/maps//" + map.getName());
        try {
            Scanner scanner = new Scanner(fFile);
            int number_of_obstacles = scanner.nextInt();
            int number_of_cameras = scanner.nextInt();
            mapWriter.write(number_of_obstacles + "\n" + number_of_cameras + "\n" + numPersons + "\n");
            scanner.nextInt(); // skip number of persons
            for (int i = 0; i < number_of_obstacles; i++) {
                int x = scanner.nextInt();
                int y = scanner.nextInt();
                int width = scanner.nextInt();
                int height = scanner.nextInt();
                obstacles.add(new Rectangle(
                        x, // The X coordinate of the upper-left corner of the Rectangle
                        y, //The Y coordinate of the upper-left corner of the Rectangle
                        width, //width
                        height));  //height
                mapWriter.write(x + " " + y + " " + width + " " + height + "\n");
            }
            mapWriter.write("\n");
            for (int i = 0; i < number_of_cameras; i++) {
                mapWriter.write(scanner.nextInt() + " " + scanner.nextInt() + "\n");// (x,y) of camera
            }
            mapWriter.write("\n");
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MapGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private Vector3f convertToWorld(Vector3f vec) {
        float xx, zz;
        xx = (float) ((320f - vec.x) * 2.811594203);
        zz = (float) ((240f - (480 - vec.z)) * 3.028821839);
        zz = -zz;
        Vector3f vect = new Vector3f(xx, 150f, zz);
        return vect;
    }
}
